<?php

/**
 * NTRSAuth will handle all user authentication. This includes creation, authentication and log out.
 **/
class NTRSAuth
{

    const SELECT_USER =
    "SELECT
        user_id, email, first_name, last_name, date_created, stat_active, stat_admin
    FROM
        nitrous_users
    WHERE
        username = @username AND
        password = @password
    LIMIT 1";

    const SELECT_USER_REMEMBER_ME = 
    "SELECT
        user_id
    FROM
        nitrous_users
    WHERE
        stat_active AND
        remember_me_hash = @remember_me_hash";

    const UPDATE_USER_REMEMBER_ME =
    "UPDATE
        nitrous_users
    SET
        remember_me_hash = @remember_me_hash
    WHERE
        user_id = #user_id";


    private
        $request,
        $errorNum,
        $errorMsg,
        $errors = array(
            0=>'Invalid username or password.',
            1=>'User disabled.'
            );

    /**
     * Create an instance of NTRSAuth and set request object
     *
     * @param   object
     **/
    public function __construct($request)
    {

        if (!$request instanceof RLRequest) {

            throw new NTRSException('NTRSAuth::__construct - Invalid request object.');

        }

        $this->request = $request;

    }

    /**
     * Connect to the database and store it in request object.
     **/
    private function connectDB()
    {

        // Only get new connection if it doesn't exist
        if (!$this->request->attribs->get('db') instanceof NTRSDatabase) {

            $db = new NTRSDatabase();
            $this->request->attribs->set('db',$db);

        }

    }

    /**
     * Set the error number and error message. The error message is set using the error number.
     *
     * @param   int
     **/
    private function setError($errorNum)
    {

        $this->errorNum = $errorNum;
        $this->errorMsg = $this->errors[$errorNum];

    }

    /**
     * Get error message
     *
     * @return  string
     **/
    public function getErrorMsg()
    {

        return $this->errorMsg;

    }

    /**
     * Get error number
     *
     * @return  int
     **/
    public function getErrorNum()
    {

        return $this->errorNum;

    }

    /**
     * Generate hash for password
     *
     * @param   string
     *
     * @return  string
     **/
    private function genPassHash($password)
    {

         return sha1(NTRS_PASSWORD_SALT . $password);

    }

    /**
     * Generate "remember me" cookie hash
     *
     * @return  string
     **/
    private function genRememberMeHash()
    {

         return md5(rand(0,99999999));

    }

    /**
     * Log user out. Remove sessions vars and remove remember me hash.
     **/
    public function logOut()
    {

        $this->request->session->set('nitrous_user', null);
        $this->request->session->set('authenticated', false);
        setcookie('nitrous_remember_me_hash', '', time()-1000);

    }

    /**
     * Authenticate user credentials, set user details in session and optionally set remember me 
     * hash in cookie.
     *
     * @param   string
     * @param   string
     * @param   bool
     *
     * @return  bool
     **/
    public function authenticate($username, $password, $setRememberMe=false)
    {

        $this->connectDB();

        $db = $this->request->attribs->get('db');

        $sql = $db->bind(self::SELECT_USER,
                            'username', $username, 
                            'password', $this->genPassHash($password));
        $db->query($sql);

        if ($db->count()) {

            $db->next();
            $user = $db->getArray();
            
            if ($user['stat_active'] == 'f') {

                // User disabled
                $this->setError(1);
                return false;

            } else {

                // Successfully logged in
                $user['username'] = $username;
                $this->request->session->set('nitrous_user', $user);
                $this->request->session->set('authenticated', true);

                // Set remember me cookie if requested
                if ($setRememberMe) {

                    $rmHash = $this->genRememberMeHash();

                    $sql = $db->bind(self::UPDATE_USER_REMEMBER_ME,
                                        'remember_me_hash', $rmHash,
                                        'user_id', $user['user_id']);
                    if ($db->exec($sql)) {

                        // Cookie stays alive for 7 days
                        setcookie('nitrous_remember_me_hash', $rmHash, time() + (7 * 86400), '/');

                    }

                }

                return true;

            }

        } else {

            // Invalid username/password
            $this->setError(0);
            return false;

        }

    }
    
    /**
     * Authenticate user using remember me hash
     *
     * @param   string      This is the remember me hash that is stored in the DB and user's cookie
     *
     * @return  bool
     **/
    public function authRememberMe()
    {

        if (isset($_COOKIE['nitrous_remember_me_hash'])) {

            $rmHash = $_COOKIE['nitrous_remember_me_hash'];
            if (strlen($rmHash)) {

                $this->connectDB();

                $db = $this->request->attribs->get('db');

                $sql = $db->bind(self::SELECT_USER_REMEMBER_ME,
                                    'remember_me_hash', $rmHash);
                $db->query($sql);

                if ($db->count()) {

                    $db->next();
                    $user = $db->getArray();
            
                    // Successfully logged in
                    $this->request->session->set('nitrous_user', $user);
                    $this->request->session->set('authenticated', true);

                    return true;

                }

            }

        }

        return false;

    }

}